﻿using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Ioc;

using Stock.Model;
using Stock.Service;
using Stock.Util;

namespace Stock.Updater.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        private AppService appService;

        public MainViewModel()
        {
            Init();
        }

        private Window _window;

        public Window Window { get => _window; set => _window = value; }

        private bool _notifyVisible;

        public bool NotifyVisible { get => _notifyVisible; set => Set(ref _notifyVisible, value); }

        private bool _checkCompleted;

        public bool CheckCompleted { get => _checkCompleted; set => Set(ref _checkCompleted, value); }

        private bool _versionVisible;

        public bool VersionVisible { get => _versionVisible; set => Set(ref _versionVisible, value); }

        private string _updateText;

        public string UpdateText { get => _updateText; set => Set(ref _updateText, value); }

        private string _buttonText;

        public string ButtonText { get => _buttonText; set => Set(ref _buttonText, value); }

        private string _upgradeText;

        public string UpgradeText { get => _upgradeText; set => Set(ref _upgradeText, value); }

        private double _processValue;

        public double ProcessValue
        {
            get => _processValue;
            set
            {
                Set(ref _processValue, value);
                if (_processValue >= 100)
                {
                    Upgrade();
                }
            }
        }

        public string SaveZipPath { get; set; }

        public RelayCommand<string> BtnClickCmd => new RelayCommand<string>(BtnClick);

        public RelayCommand ExitCmd => new RelayCommand(Exit);

        private async void Init()
        {
            appService = SimpleIoc.Default.GetInstance<AppService>();
            ButtonText = AppConst.TEXT_CHECK_NOW;
            UpdateText = AppConst.TEXT_CHECK_NOW;
            await CheckVersion();
        }

        private void Exit()
        {
            NotifyVisible = false;
            Application.Current.Shutdown();
        }

        private void ShowWindow()
        {
            Application.Current.Dispatcher?.Invoke(() => _window.Show());
        }

        private async Task CheckVersion()
        {
            string filePath = GetAppPath();
            if (string.IsNullOrEmpty(filePath))
            {
                return;
            }

            var updateModel = await appService.GetLastVersion();
            if (updateModel.HasVersion())
            {
                CheckCompleted = true;
                string version = FileUtil.GetFileVersion(filePath);
                Version currentVersion = StringUtil.GetVersion(version);
                if (updateModel.Version > currentVersion)
                {
                    VersionVisible = true;
                    ButtonText = AppConst.TEXT_UPDATE_BEHIND;
                    UpdateText = updateModel.Name;
                    UpgradeText = AppConst.TEXT_UPGRADE_1;

                    await DownloadApp(updateModel);
                }
                else
                {
                    VersionVisible = false;
                    ButtonText = AppConst.TEXT_GOOD;
                    UpdateText = string.Format(AppConst.TEXT_CURRENT_VERSION_IS_NEW, AppConst.APP_VERSION);
                }
            }
        }

        private async Task DownloadApp(AppUpdateModel model)
        {
            string saveFilePath = FileUtil.GetParentFilePath($"Temp\\{FileUtil.GetFileName(model.DownloadUrl)}");
            SaveZipPath = saveFilePath;

            await appService.DownloadApp(model.DownloadUrl, saveFilePath, (d1, d2) =>
            {
                ProcessValue = (int)(d1 * 100 / d2);
            }, d2 =>
            {
                ProcessValue = 100;
            });
        }

        private void Upgrade()
        {
            UpgradeText = AppConst.TEXT_UPGRADE_2;
            ProcessUtil.Kill(AppConst.TEXT_APP_EN_NAME);
            Thread.Sleep(1000);

            string dataPath = AppConst.TEXT_APP_DATA_DIR;
            string dataPath2 = AppConst.TEXT_APP_UPDATER_EN_NAME + "/";
            UpgradeText = AppConst.TEXT_UPGRADE_3;
            bool flag = ZipUtil.UnZip(SaveZipPath, FileUtil.GetParentPath(), (p, fullName) =>
            {
                return fullName.StartsWith(dataPath) || fullName.StartsWith(dataPath2);
            });
            Thread.Sleep(1000);

            if (flag)
            {
                //UpgradeText = AppConst.TEXT_UPGRADE_4;
                //StartApp();
                //Thread.Sleep(1000);

                UpgradeText = AppConst.TEXT_UPDATE_COMPLETED;
                ButtonText = AppConst.TEXT_UPDATE_COMPLETED;
            }
            else
            {
                ButtonText = AppConst.TEXT_UPDATE_FAIL;
                UpgradeText = AppConst.TEXT_UPDATE_FAIL;
            }

            if (NotifyVisible)
            {
                ShowWindow();
            }
        }

        private void BtnClick(string text)
        {
            switch (text)
            {
                case AppConst.TEXT_GOOD:
                case AppConst.TEXT_UPDATE_FAIL:
                    Exit();
                    break;
                case AppConst.TEXT_UPDATE_BEHIND:
                    _window.Close();
                    break;
                case AppConst.TEXT_UPDATE_COMPLETED:
                    StartApp();
                    Exit();
                    break;
            }
        }

        private void StartApp()
        {
            string fileName = GetAppPath();
            ProcessUtil.Start(fileName);
        }

        private string GetAppPath()
        {
            string filePath = FileUtil.GetParentFilePath($"{AppConst.TEXT_APP_EN_NAME}.exe");
            if (FileUtil.ExistFile(filePath))
            {
                return filePath;
            }
            return string.Empty;
        }
    }
}
